/*
 * @Author: hzm 
 * @Date: 2020-06-20 22:29:01 
 * @Last Modified by:   hzm 
 * @Last Modified time: 2020-06-20 22:29:01 
 */


#include "MLogManager.h"
#include <time.h>
#include <sys/stat.h>
#include <iostream>
#include <fstream>

#ifndef _WIN32
#include <unistd.h>
#endif

#include "spdlog/sinks/stdout_color_sinks.h"

using namespace HeyIM;
using namespace std;

static const std::string K_ANDROID_lOGGER_TAG = MSGKIT_NAME;

MLog& MLog::Instance() {
    static MLog* log = new MLog;
            
    return *log;
}

void MLog::InitMLog(const std::string& loggerName, const std::string& fileName, level::level_enum logLevel) {
    
    m_logFilePath = fileName;
    m_level = logLevel;

    //打开或者创建本地log文件
    ofstream fileHandler;
    fileHandler.open(fileName, ios::out | ios::trunc);

    if(!fileHandler.is_open()) {
        MLogError("{} open or create failed", fileName);
    }
    
    setupLogger(loggerName);
    
    fileHandler.close();
    
    start();
}

void MLog::setupLogger(const std::string& loggerName) {
    
        //初始化logger
    #ifdef __ANDROID__
        m_logger = android_logger_mt(loggerName, loggerName);
    #else
        auto console_sink = std::make_shared<sinks::stdout_color_sink_mt>();
        console_sink->set_level(m_level);
        console_sink->set_pattern("[MessageKit] [%^%l%$] %v");

        auto file_sink = std::make_shared<sinks::basic_file_sink_mt>(m_logFilePath, true);
        file_sink->set_level(m_level);

        std::shared_ptr<logger> loggerPtr(new logger(MSGKIT_NAME, {console_sink, file_sink}));
    
        m_logger = loggerPtr;
    #endif
    
    m_logger -> set_level(m_level);
    
    //当遇到错误级别以上的立刻刷新到日志
    m_logger -> flush_on(spdlog::level::err);
    //每三秒刷新一次
    flush_every(std::chrono::seconds(3));
}

void MLog::start() {
    
    m_logOpenMutex.lock();
    m_isLogWriteToFile = true;
    m_logOpenMutex.unlock();
}

void MLog::OpenTraceLog() {
    m_logOpenMutex.lock();
    if(m_isLogWriteToFile) {
        m_logOpenMutex.unlock();
        return;
    }
    m_logOpenMutex.unlock();
    start();
}

void MLog::getCurrentTimeStr(std::string& timeStr) const {
    time_t rawtime;
    struct tm *ptminfo;
    time(&rawtime);
    ptminfo = localtime(&rawtime);
    
    char* cstr = (char*)malloc(50);
    sprintf(cstr, "%02d-%02d-%02d %02d:%02d:%02d",
            ptminfo->tm_year + 1900, ptminfo->tm_mon + 1, ptminfo->tm_mday,
            ptminfo->tm_hour, ptminfo->tm_min, ptminfo->tm_sec);
    
    timeStr = cstr;
    
    free(cstr);
}

void MLog::EndLog() {
    m_logOpenMutex.lock();
    m_isLogWriteToFile = false;
    m_logOpenMutex.unlock();
    spdlog::shutdown();
}

MLog::MLog()
{
    
}

MLog::~MLog()
{
    EndLog();
}


void MLog::SetLevel(level::level_enum level) {
    m_level = level;
    m_logger->set_level(level);
}

bool MLog::logFileExist(const std::string& name) {
    struct stat buffer;
    return (stat (name.c_str(), &buffer) == 0);
}

